package br.com.vdn.negocio;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;

import br.com.util.exception.UtilException;
import br.com.util.hibernate.business.HbNgc;
import br.com.util.hibernate.business.HibernateUtil;
import br.com.util.hibernate.business.NegocioThrow;
import br.com.util.hibernate.business.RestritorHb;
import br.com.util.tipodado.DataHora;
import br.com.util.tipodado.Flag;
import br.com.util.tipodado.YesNo;
import br.com.vdn.vo.ItensVendaVo;
import br.com.vdn.vo.VendaVo;

@SuppressWarnings("unchecked")
public class VendaNgc extends HbNgc<VendaVo>
{
	private Map filtroPropriedade = new HashMap();
	private Map restritores = new HashMap();
	
	public static final int JOIN_CLIENTE = 1;
	public static final int JOIN_VENDEDOR = 2;
	public static final int JOIN_ARQUITETO = 4;
	public static final int JOIN_USUARIOINCLUSAO = 8;
	public static final int JOIN_ITENSVENDA = 16;
	public static final int JOIN_ENDERECOENTREGA = 32;
	public static final int JOIN_ENDERECOCOBRANCA = 64;
	
	private static VendaNgc instancia = null;
	
	public static VendaNgc getInstancia()
	{
		if (instancia == null)
		{
			instancia = new VendaNgc();
		}
		return instancia;
	}
	
	private VendaNgc()
	{
		addFiltro("codigo", RestritorHb.RESTRITOR_EQ, "codigo");
		addFiltro("cliente.codigo", RestritorHb.RESTRITOR_EQ, "clienteVo.codigo");
		addFiltro("vendedor.codigo", RestritorHb.RESTRITOR_EQ, "vendedorVo.codigo");
		addFiltro("arquiteto.codigo", RestritorHb.RESTRITOR_EQ, "arquitetoVo.codigo");
		addFiltro("dataInclusao", RestritorHb.RESTRITOR_DATA_INICIAL, "filtro.dataInclusaoInicio.dataHora");
		addFiltro("dataInclusao", RestritorHb.RESTRITOR_DATA_FINAL, "filtro.dataInclusaoFim.dataHora");
		addFiltro("valorDesconto", RestritorHb.RESTRITOR_GE, "filtro.valorDescontoInicio");
		addFiltro("valorDesconto", RestritorHb.RESTRITOR_LE, "filtro.valorDescontoFim");
		addFiltro("valorTotal", RestritorHb.RESTRITOR_GE, "filtro.valorTotalInicio");
		addFiltro("valorTotal", RestritorHb.RESTRITOR_LE, "filtro.valorTotalFim");
		addFiltro("listaItensVenda.flagAtivo", RestritorHb.RESTRITOR_EQ, "filtro.flagAtivoItensVenda");
		addFiltro("flagAtivo", RestritorHb.RESTRITOR_EQ, "flagAtivo");
		addFiltro("dataVenda", RestritorHb.RESTRITOR_DATA_INICIAL, "filtro.dataVendaInicio");
		addFiltro("dataVenda", RestritorHb.RESTRITOR_DATA_FINAL, "filtro.dataVendaFim");
		addFiltro("valorFinal", RestritorHb.RESTRITOR_GE, "filtro.valorFinalInicio");
		addFiltro("valorFinal", RestritorHb.RESTRITOR_LE, "filtro.valorFinalFim");
	}

	@Override
	protected Criteria montaCriteria(Session session, int join)
	{
		Criteria criteria = session.createCriteria(VendaVo.class);
		
		if ((join & JOIN_CLIENTE) != 0)
		{
			criteria.createCriteria("clienteVo", "cliente", Criteria.INNER_JOIN);
		}
		if ((join & JOIN_VENDEDOR) != 0)
		{
			criteria.createCriteria("vendedorVo", "vendedor", Criteria.INNER_JOIN);
		}
		if ((join & JOIN_ARQUITETO) != 0)
		{
			criteria.createCriteria("arquitetoVo", "arquiteto", Criteria.LEFT_JOIN);
		}
		if ((join & JOIN_ENDERECOENTREGA) != 0)
		{
			criteria.createCriteria("enderecoEntregaVo", "enderecoEntrega", Criteria.LEFT_JOIN);
		}
		if ((join & JOIN_ENDERECOCOBRANCA) != 0)
		{
			criteria.createCriteria("enderecoCobrancaVo", "enderecoCobranca", Criteria.LEFT_JOIN);
		}
		if ((join & JOIN_USUARIOINCLUSAO) != 0)
		{
			criteria.createCriteria("usuarioInclusaoVo", "usuarioInclusao", Criteria.INNER_JOIN);
		}
		if ((join & JOIN_ITENSVENDA) != 0)
		{
			criteria.createCriteria("listaItensVenda", "listaItensVenda", Criteria.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		}
		
		return criteria;
	}
	
	@Override
	public VendaVo inserir(Session sessao, VendaVo vo) throws UtilException
	{
		List<ItensVendaVo> listaItensVenda = new ArrayList<ItensVendaVo>(vo.getListaItensVenda());
		vo.setListaItensVenda(null);
		
		vo = super.inserir(sessao, vo);
		
		sessao.flush();
		
		if (listaItensVenda != null
				&& listaItensVenda.size() > 0)
		{
			Iterator<ItensVendaVo> iterator = listaItensVenda.iterator();
			while(iterator.hasNext())
			{
				ItensVendaVo elemento = iterator.next();
				elemento.setVendaVo(vo);
				ItensVendaNgc.getInstancia().inserir(sessao, elemento);
			}
		}
		
		return vo;
	}
	
	@Override
	public VendaVo alterar(Session sessao, VendaVo vo) throws UtilException
	{
		List<ItensVendaVo> listaItensVenda = new ArrayList<ItensVendaVo>(vo.getListaItensVenda());
		vo.setListaItensVenda(null);
		
		vo = super.alterar(sessao, vo);
		
		sessao.flush();
		
		if (listaItensVenda != null
				&& listaItensVenda.size() > 0)
		{
			Iterator<ItensVendaVo> iterator = listaItensVenda.iterator();
			while(iterator.hasNext())
			{
				ItensVendaVo elemento = iterator.next();
				if (elemento.getCodigo() == null
						|| !elemento.getCodigo().isPreenchido())
				{
					elemento.setVendaVo(vo);
					ItensVendaNgc.getInstancia().inserir(sessao, elemento);
				}
				else
				{
					ItensVendaNgc.getInstancia().alterar(sessao, elemento);
				}
			}
		}
		
		return vo; 
	}
	
	@Override
	protected void setarOrdenacao(Criteria criteria, VendaVo filter, int join)
	{
		if ((join & JOIN_CLIENTE) != 0)
		{
			criteria.addOrder(Order.asc("cliente.nome"));
		}
		if ((join & JOIN_ITENSVENDA) != 0)
		{
			criteria.addOrder(Order.asc("listaItensVenda.sequencial"));
		}
	}
	
	@Override
	protected Map filtroPropriedade()
	{
		return filtroPropriedade;
	}

	@Override
	protected Map restritores()
	{
		return restritores;
	}

	public void cancelarVenda(VendaVo vo) throws UtilException
	{
		Session sessao = HibernateUtil.getSession();
		sessao.setFlushMode(FlushMode.COMMIT);
		Transaction tx = sessao.beginTransaction();
		try
		{
			cancelarVenda(sessao, vo);
			tx.commit();
		}
		catch (Exception e)
		{
			throw NegocioThrow.getInstancia().catchHBEdicaoSession(e, tx);
		}
		finally
		{
			sessao.close();
		}
	}

	public void cancelarVenda(Session sessao, VendaVo vo)
		throws UtilException
	{
		List<ItensVendaVo> listaItensVenda = new ArrayList<ItensVendaVo>(vo.getListaItensVenda());
		vo.setListaItensVenda(null);
		
		vo.setFlagAtivo(new Flag(YesNo.NO));
		vo = super.alterar(sessao, vo);
		
		Iterator<ItensVendaVo> iterator = listaItensVenda.iterator();
		while(iterator.hasNext())
		{
			ItensVendaVo elemento = iterator.next();
			elemento.setFlagAtivo(new Flag(YesNo.NO));
			elemento.setUsuarioAlteracaoVo(vo.getUsuarioAlteracaoVo());
			elemento.setDataAlteracao(new DataHora(new Date().getTime()));
			ItensVendaNgc.getInstancia().alterar(sessao, elemento);
		}
	}

}
